﻿using System;
using System.Threading;
using System.Windows.Threading;

namespace Iorz.DomainSearch.Utils.Worker
{
    public class BaseWorker
    {
        /// <summary>
        /// 线程状态
        /// </summary>
        public enum WorkerStatus
        {
            Idle = 0, // 线程处于无动作状态
            Running = 1, // 线程处于运行状态
            WaitFor = 2, // 线程处于被等待结束状态
            Disposed = 3, // 线程处于已被释放状态
        }

        /// <summary>
        /// 线程间隔时间(毫秒)
        /// </summary>
        public const int mInterval = 1000;

        /// <summary>
        /// 线程结束事件
        /// </summary>
        public Action OnTerminated { private get; set; }

        // 工作线程
        private Thread mThread;

        // 等待线程数量
        private Int32 mWaitCount = 0;

        // 线程运行标志
        private Boolean mRunFlag = false;

        // 线程状态
        private WorkerStatus mStatus = WorkerStatus.Idle;

        // 工作线程锁
        protected Object mLock;

        // UI控件
        protected Dispatcher mOwner;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="owner">UI控件</param>
        public BaseWorker(Dispatcher owner)
        {
            if (owner == null)
                throw new System.ArgumentException("owner is null!");

            mOwner = owner;
            mLock = new Object();
        }

        /// <summary>
        /// 析构函数
        /// </summary>
        ~BaseWorker()
        {
            Discard();
            WaitFor();
        }

        /// <summary>
        /// 启动函数
        /// </summary>
        /// <returns>启动结果</returns>
        public virtual bool Start()
        {
            lock (mLock)
            {
                if (mStatus != WorkerStatus.Idle)
                    return false;

                mStatus = WorkerStatus.Running;
                mRunFlag = true;

                try
                {
                    mThread = new Thread(Execute);
                    mThread.Start();
                }
                catch
                {
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// 等待工作线程结束
        /// </summary>
        public virtual void WaitFor()
        {
            lock (mLock)
            {
                if (mStatus == WorkerStatus.Idle)
                {
                    return;
                }

                mStatus = WorkerStatus.WaitFor;
                mWaitCount++;
            }

            if (mThread != null)
                mThread.Join();

            lock (mLock)
            {
                if (--mWaitCount > 0)
                {
                    return;
                }

                mStatus = WorkerStatus.Idle;
            }
        }

        /// <summary>
        /// 请求终止线程
        /// </summary>
        /// <param name="userData">用户参数</param>
        public void NotifyToStop()
        {
            lock (mLock)
            {
                if (mRunFlag)
                {
                    mRunFlag = false;
                }
            }
        }

        /// <summary>
        /// 抛弃工作线程
        /// </summary>
        public virtual void Discard()
        {
            lock (mLock)
            {
                OnTerminated = null;
                NotifyToStop();
            }
        }

        /// <summary>
        /// 是否终止运行
        /// </summary>
        /// <returns>终止运行标志</returns>
        public Boolean IsTerminated()
        {
            Boolean ret;

            lock (mLock)
            {
                ret = (mRunFlag == false);
            }

            return ret;
        }

        /// <summary>
        /// 线程是否处于无动作状态
        /// </summary>
        /// <returns>无动作状态标志</returns>
        public Boolean IsIdle()
        {
            Boolean ret;

            lock (mLock)
            {
                ret = (mStatus == WorkerStatus.Idle);
            }

            return ret;
        }

        /// <summary>
        /// 执行函数
        /// </summary>
        private void Execute()
        {
            Run();

            lock (mLock)
            {
                NotifyToStop();

                if (OnTerminated != null)
                    Asynchronous(OnTerminated);

                if (mStatus == WorkerStatus.Running)
                    mStatus = WorkerStatus.Idle;
            }
        }

        /// <summary>
        /// 执行函数
        /// </summary>
        protected virtual void Run()
        {
        }

        /// <summary>
        /// UI线程异步执行代理
        /// </summary>
        /// <param name="method">代理</param>
        /// <param name="args">参数列表</param>
        protected virtual void Asynchronous(
            Delegate method, params Object[] args)
        {
            if ((method != null) && (mOwner != null) && !(mOwner.HasShutdownFinished || mOwner.HasShutdownStarted))
                mOwner.BeginInvoke(method, args);
        }

        /// <summary>
        /// UI线程同步执行代理
        /// </summary>
        /// <param name="method">代理</param>
        /// <param name="args">参数列表</param>
        protected virtual void Synchronize(
            Delegate method, params Object[] args)
        {
            if ((method != null) && (mOwner != null) && !(mOwner.HasShutdownFinished || mOwner.HasShutdownStarted))
                mOwner.Invoke(method, args);
        }
    }
}
